package blackstar.performance.logger.info;

import java.util.HashMap;
import java.util.Map;

import blackstar.performance.logger.MessageBuilder;
import blackstar.performance.logger.RollingFileLogger;

/**
 * @author raywu (ayufox@gmail.com)
 * 
 */
public class LoadLogger
{
	public final static int BEGIN = 1;
	public final static int END = 2;
	private Map<Long, LoadChainTree> loadChainTreeMap = new HashMap<Long, LoadChainTree>();
	private RollingFileLogger rollingFileLogger;
	private boolean appendTime = false;//是否输出时间信息

	public LoadLogger(RollingFileLogger rollingFileLogger, boolean appendTime)
	{
		this.rollingFileLogger = rollingFileLogger;
		this.appendTime = appendTime;
	}

	/**
	 * @param className
	 * @param methodName
	 */
	public void start(String className, String methodName)
	{
		Thread t = Thread.currentThread();

		start(t.getId(), className, methodName);
	}

	/**
	 * @param threadId
	 * @param className
	 * @param methodName
	 */
	public void start(long threadId, String className, String methodName)
	{
		LoadChainTree tree = this.loadChainTreeMap.get(threadId);
		if (tree == null)
		{
			tree = new LoadChainTree();
			this.loadChainTreeMap.put(threadId, tree);
		}
		tree.start(className, methodName, System.nanoTime());
	}

	public long stop()
	{
		Thread t = Thread.currentThread();
		return stop(t.getId());
	}

	/**
	 * @param threadId
	 */
	public long stop(long threadId)
	{
		LoadChainTree tree = this.loadChainTreeMap.get(threadId);
		if (tree != null)
		{
			tree.stop(System.nanoTime());

			if (tree.isFinish())
			{
				final MessageBuilder builder = new MessageBuilder(1024);
				tree.getRoot().visitDepthFirst(new INodeVisitor(){
					public void visitBegin(LoadChainNode node)
					{
						log(BEGIN, node);
					}

					public void visitEnd(LoadChainNode node)
					{
						log(END, node);
					}
					
					private void log(int type, LoadChainNode node)
					{
						builder.append(type);
						builder.appendSplit();
						builder.append(node.getClassName());
						builder.appendSplit();
						builder.append(node.getMethod());
						builder.appendSplit();
						builder.append(node.getTimeNano());
						if (appendTime)
						{
							builder.appendSplit();
							builder.appendTimestamp();
						}
						builder.appendLineSep();
					}
				});
				rollingFileLogger.log(builder.getMessage());

				this.loadChainTreeMap.remove(threadId);
				
				return tree.getRoot().getTimeNano();
			}
		}
		
		return 0;
	}
}
